package com.nbcio.cd.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaMode;
import com.nbcio.cd.domain.vo.CdShareVo;
import com.nbcio.cd.domain.vo.CdFileVo;
import com.nbcio.cd.service.ICdShareService;
import com.nbcio.common.core.domain.R;
import com.nbcio.common.log.annotation.Log;
import com.nbcio.common.log.enums.BusinessType;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.List;

/**
 * 云网盘分享Controller
 *
 * @author nbacheng
 */
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/cd/share")
public class CdShareController {

    private final ICdShareService cdShareService;

    /**
     * 创建分享
     */
    @SaCheckPermission("cd:share:add")
    @Log(title = "云网盘分享", businessType = BusinessType.INSERT)
    @PostMapping("/create")
    public R<CdShareVo> createShare(@RequestParam @NotEmpty(message = "分享类型不能为空") String shareType,
                                   @RequestParam @NotNull(message = "资源ID不能为空") Long resourceId,
                                   @RequestParam @NotEmpty(message = "分享名称不能为空") String shareName,
                                   @RequestParam(required = false) String sharePassword,
                                   @RequestParam(required = false) Date expireTime,
                                   @RequestParam(defaultValue = "public") String accessLevel,
                                   @RequestParam(defaultValue = "true") Boolean allowDownload,
                                   @RequestParam(defaultValue = "true") Boolean allowPreview) {
        try {
            CdShareVo shareVo = cdShareService.createShare(shareType, resourceId, shareName, 
                    sharePassword, expireTime, accessLevel, allowDownload, allowPreview);
            return R.ok(shareVo);
        } catch (Exception e) {
            log.error("创建分享失败: {}", e.getMessage(), e);
            return R.fail("创建分享失败: " + e.getMessage());
        }
    }

    /**
     * 获取分享信息
     */
    @GetMapping("/info/{shareCode}")
    @SaCheckPermission(value = "", mode = SaMode.OR)
    public R<CdShareVo> getShareInfo(@PathVariable @NotEmpty(message = "分享码不能为空") String shareCode) {
        try {
            CdShareVo shareVo = cdShareService.getShareInfo(shareCode);
            return R.ok(shareVo);
        } catch (Exception e) {
            log.error("获取分享信息失败: {}", e.getMessage(), e);
            return R.fail("获取分享信息失败: " + e.getMessage());
        }
    }

    /**
     * 验证分享密码
     */
    @PostMapping("/validatePassword")
    @SaCheckPermission(value = "", mode = SaMode.OR)
    public R<Boolean> validateSharePassword(@RequestParam @NotEmpty(message = "分享码不能为空") String shareCode,
                                          @RequestParam(required = false) String password) {
        try {
            Boolean isValid = cdShareService.validateSharePassword(shareCode, password);
            return R.ok(isValid);
        } catch (Exception e) {
            log.error("验证分享密码失败: {}", e.getMessage(), e);
            return R.fail("验证分享密码失败: " + e.getMessage());
        }
    }

    /**
     * 通过分享码下载文件
     */
    @GetMapping("/download/{shareCode}")
    @SaCheckPermission(value = "", mode = SaMode.OR)
    public void downloadFileByShare(@PathVariable @NotEmpty(message = "分享码不能为空") String shareCode,
                                   HttpServletResponse response) {
        try {
            cdShareService.downloadFileByShare(shareCode, response);
        } catch (Exception e) {
            log.error("通过分享下载文件失败: {}", e.getMessage(), e);
            try {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                response.getWriter().write("下载失败: " + e.getMessage());
            } catch (IOException ignored) {
            }
        }
    }

    /**
     * 通过分享码预览文件
     */
    @GetMapping("/preview/{shareCode}")
    @SaCheckPermission(value = "", mode = SaMode.OR)
    public void previewFileByShare(@PathVariable @NotEmpty(message = "分享码不能为空") String shareCode,
                                  HttpServletResponse response) {
        try {
            cdShareService.previewFileByShare(shareCode, response);
        } catch (Exception e) {
            log.error("通过分享预览文件失败: {}", e.getMessage(), e);
            try {
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                response.getWriter().write("预览失败: " + e.getMessage());
            } catch (IOException ignored) {
            }
        }
    }

    /**
     * 通过分享码获取文件信息
     */
    @GetMapping("/file-info/{shareCode}")
    @SaCheckPermission(value = "", mode = SaMode.OR)
    public R<CdFileVo> getFileInfoByShare(@PathVariable @NotEmpty(message = "分享码不能为空") String shareCode) {
        try {
            CdFileVo fileVo = cdShareService.getFileInfoByShare(shareCode);
            return R.ok(fileVo);
        } catch (Exception e) {
            log.error("通过分享获取文件信息失败: {}", e.getMessage(), e);
            return R.fail("获取文件信息失败: " + e.getMessage());
        }
    }

    /**
     * 更新分享设置
     */
    @SaCheckPermission("cd:share:edit")
    @Log(title = "云网盘分享", businessType = BusinessType.UPDATE)
    @PutMapping("/update")
    public R<Boolean> updateShareSettings(@RequestParam @NotNull(message = "分享ID不能为空") Long shareId,
                                        @RequestParam @NotEmpty(message = "分享名称不能为空") String shareName,
                                        @RequestParam(required = false) String sharePassword,
                                        @RequestParam(required = false) Date expireTime,
                                        @RequestParam(defaultValue = "public") String accessLevel,
                                        @RequestParam(defaultValue = "true") Boolean allowDownload,
                                        @RequestParam(defaultValue = "true") Boolean allowPreview) {
        try {
            Boolean result = cdShareService.updateShareSettings(shareId, shareName, sharePassword,
                    expireTime, accessLevel, allowDownload, allowPreview);
            return R.ok(result);
        } catch (Exception e) {
            log.error("更新分享设置失败: {}", e.getMessage(), e);
            return R.fail("更新分享设置失败: " + e.getMessage());
        }
    }

    /**
     * 删除分享
     */
    @SaCheckPermission("cd:share:remove")
    @Log(title = "云网盘分享", businessType = BusinessType.DELETE)
    @DeleteMapping("/{shareId}")
    public R<Boolean> deleteShare(@PathVariable @NotNull(message = "分享ID不能为空") Long shareId) {
        try {
            Boolean result = cdShareService.deleteShare(shareId);
            return R.ok(result);
        } catch (Exception e) {
            log.error("删除分享失败: {}", e.getMessage(), e);
            return R.fail("删除分享失败: " + e.getMessage());
        }
    }

    /**
     * 获取用户分享列表
     */
    @SaCheckPermission("cd:share:list")
    @GetMapping("/userShares")
    public R<List<CdShareVo>> getUserShares(@RequestParam @NotNull(message = "用户ID不能为空") Long userId) {
        try {
            List<CdShareVo> shares = cdShareService.getUserShares(userId);
            return R.ok(shares);
        } catch (Exception e) {
            log.error("获取用户分享列表失败: {}", e.getMessage(), e);
            return R.fail("获取用户分享列表失败: " + e.getMessage());
        }
    }

    /**
     * 清理过期分享
     */
    @SaCheckPermission("cd:share:remove")
    @Log(title = "云网盘分享", businessType = BusinessType.DELETE)
    @PostMapping("/cleanExpired")
    public R<Void> cleanExpiredShares() {
        try {
            cdShareService.cleanExpiredShares();
            return R.ok();
        } catch (Exception e) {
            log.error("清理过期分享失败: {}", e.getMessage(), e);
            return R.fail("清理过期分享失败: " + e.getMessage());
        }
    }
}
